package cn.slipi.common.utils;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.UnsupportedEncodingException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @author lee
 */
public class StrUtils extends StringUtils {

    private static final Logger LOG = LoggerFactory.getLogger(StrUtils.class);


    public static String generateUUID() {
        return UUID.randomUUID().toString().replace("-", "");
    }

    public static List<Long> stringToLongList(String info, String sp) {
        if (StrUtils.isNotBlank(info)) {
            sp = sp == null ? "," : sp;
            return Arrays.stream(info.split(sp)).map(s -> Long.parseLong(s.trim())).collect(Collectors.toList());
        }
        return new ArrayList<>();
    }

    public static List<Integer> stringToIntList(String info, String sp) {
        if (StrUtils.isNotBlank(info)) {
            sp = sp == null ? "," : sp;
            return Arrays.stream(info.split(sp)).map(s -> Integer.parseInt(s.trim())).collect(Collectors.toList());
        }
        return new ArrayList<>();
    }

    public static List<String> stringToList(String info, String sp) {
        if (StrUtils.isNotBlank(info)) {
            sp = sp == null ? "," : sp;
            return Arrays.asList(info.split(sp));
        }
        return new ArrayList<>();
    }

    public static String getUtf8(String iosStr) {
        LOG.debug(String.format("pre:%s", iosStr));
        try {
            if (StrUtils.isNotBlank(iosStr)) {
                iosStr = new String(iosStr.getBytes("iso8859-1"), "utf-8");
                LOG.debug(String.format("after:%s", iosStr));
            }
        } catch (UnsupportedEncodingException e) {
            LOG.error("参数转码出错", e);
        }
        return iosStr;
    }


    public static String getProfile() {
        String env = System.getProperty("spring.profiles.active");
        if (env == null) {
            env = System.getenv("spring.profiles.active");
        }
        return StringUtils.defaultString(env, "de");
    }


    public static boolean isEmpty(Object obj) {
        try {
            if (obj == null) {
                return true;
            } else if (StringUtils.isBlank(obj.toString())) {
                return true;
            }
        } catch (Exception e) {
            return true;
        }
        return false;
    }

    /**
     * unicode转中文
     *
     * @param unicode
     * @return
     */
    public static String unicodeToCn(String unicode) {
        String ptn = "(\\\\u(\\p{XDigit}{4}))";
        Pattern pattern = Pattern.compile(ptn);
        Matcher matcher = pattern.matcher(unicode);
        char ch;
        while (matcher.find()) {
            ch = (char) Integer.parseInt(matcher.group(2), 16);
            unicode = unicode.replace(matcher.group(1), ch + "");
        }
        return unicode;
    }

    /**
     * 中文转unicode
     *
     * @param cn
     * @return
     */
    public static String cnToUnicode(String cn) {
        String result = "";
        for (int i = 0; i < cn.length(); i++) {
            int chr1 = (char) cn.charAt(i);
            //汉字范围 \u4e00-\u9fa5 (中文)
            if (chr1 >= 19968 && chr1 <= 171941) {
                result += "\\u" + Integer.toHexString(chr1);
            } else {
                result += cn.charAt(i);
            }
        }
        return result;
    }

    /**
     * 采用动态规划的方法（字符串匹配相似度）
     *
     * @param source 源
     * @param target 要匹配的字符串
     * @return
     */
    public static int calcSimilar(String source, String target) {
        char[] sources = source.toCharArray();
        char[] targets = target.toCharArray();
        int sourceLen = sources.length;
        int targetLen = targets.length;
        int[][] d = new int[sourceLen + 1][targetLen + 1];
        for (int i = 0; i <= sourceLen; i++) {
            d[i][0] = i;
        }
        for (int i = 0; i <= targetLen; i++) {
            d[0][i] = i;
        }

        for (int i = 1; i <= sourceLen; i++) {
            for (int j = 1; j <= targetLen; j++) {
                if (sources[i - 1] == targets[j - 1]) {
                    d[i][j] = d[i - 1][j - 1];
                } else {
                    //插入
                    int insert = d[i][j - 1] + 1;
                    //删除
                    int delete = d[i - 1][j] + 1;
                    //替换
                    int replace = d[i - 1][j - 1] + 1;
                    d[i][j] = Math.min(insert, delete) > Math.min(delete, replace) ? Math.min(delete, replace) :
                            Math.min(insert, delete);
                }
            }
        }
        return d[sourceLen][targetLen];
    }

    /**
     * 只显示第一个汉字，其他隐藏为2个星号<例子：李**>
     *
     * @param fullName
     * @param index    1 为第index位
     * @return
     */
    public static String left(String fullName, int index) {
        if (isBlank(fullName)) {
            return "";
        }
        String name = StringUtils.left(fullName, index);
        return StringUtils.rightPad(name, StringUtils.length(fullName), "*");
    }

    /**
     * [身份证号] 110****58，前面保留3位明文，后面保留2位明文
     *
     * @param name
     * @param index 3
     * @param end   2
     * @return
     */
    public static String around(String name, int index, int end) {
        if (StringUtils.isBlank(name)) {
            return "";
        }
        return StringUtils.left(name, index).concat(StringUtils.removeStart(StringUtils.leftPad(StringUtils.right(name, end), StringUtils.length(name), "*"), "***"));
    }

    /**
     * [固定电话] 后四位，其他隐藏<例子：****1234>
     *
     * @param num
     * @return
     */
    public static String right(String num, int end) {
        if (StringUtils.isBlank(num)) {
            return "";
        }
        return StringUtils.leftPad(StringUtils.right(num, end), StringUtils.length(num), "*");
    }

    public static String phone(String phone) {
        return phone.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2");
    }


    /**
     * 把原始字符串分割成指定长度的字符串列表
     *
     * @param inputString 原始字符串
     * @param length      指定长度
     * @return
     */
    public static List<String> getStrList(String inputString, int length) {
        int size = inputString.length() / length;
        if (inputString.length() % length != 0) {
            size += 1;
        }
        return getStrList(inputString, length, size);
    }

    /**
     * 把原始字符串分割成指定长度的字符串列表
     *
     * @param inputString 原始字符串
     * @param length      指定长度
     * @param size        指定列表大小
     * @return
     */
    public static List<String> getStrList(String inputString, int length, int size) {
        List<String> list = new ArrayList<String>();
        for (int index = 0; index < size; index++) {
            String childStr = substring(inputString, index * length,
                    (index + 1) * length);
            list.add(childStr);
        }
        return list;
    }

    /**
     * 分割字符串，如果开始位置大于字符串长度，返回空
     *
     * @param str 原始字符串
     * @param f   开始位置
     * @param t   结束位置
     * @return
     */
    public static String substring(String str, int f, int t) {
        if (f > str.length()) {
            if (t > str.length()) {
                return str.substring(f, str.length());
            } else {
                return str.substring(f, t);
            }
        }
        return "";
    }

    public static String listToString(List list, char separator) {
        StringBuilder sb = new StringBuilder();
        for (Object o : list) {
            sb.append(o).append(separator);
        }
        return list.isEmpty() ? "" : sb.toString().substring(0, sb.toString().length() - 1);
    }


    public static String formatNum(String source, int length, String fillStr) {
        int sourceSize = source.length();
        if (sourceSize == length) {
            //长度相等直接返回
            return source;
        } else if (sourceSize > length) {
            //需要截取后length
            return source.substring(sourceSize - length);
        } else {
            //需要填充长度
            int needPadSize = length - sourceSize;
            char[] strArr = fillStr.toCharArray();
            StringBuilder sb = new StringBuilder(length);
            int fillSize = strArr.length;
            if (fillSize > needPadSize) {
                sb.append(new String(strArr, 0, needPadSize));
            } else {
                int r = needPadSize / fillSize;
                for (int i = 0; i < r; i++) {
                    sb.append(fillStr);
                }
                //不能整除
                int left = needPadSize % fillSize;
                if (left != 0) {
                    sb.append(new String(strArr, 0, left));
                }
            }
            sb.append(source);
            return sb.toString();
        }
    }

    /**
     * 判断一个字符串是否都为数字
     *
     * @param strNum
     * @return
     */
    public static boolean isAllDigit(String strNum) {
        return strNum.matches("[0-9]{1,}");
    }


    /**
     * 字符串中获取数字
     *
     * @param str
     * @return
     */
    public static String getNumByStr(String str) {
        String regEx = "[^0-9]";
        Pattern p = Pattern.compile(regEx);
        Matcher m = p.matcher(str);
        return m.replaceAll("").trim();
    }

    public static List<Map<String, String>> addressPattern(String address) {
        String regex = "((?<province>[^省]+省|.+自治区)|上海|北京|天津|重庆)(?<city>[^市]+市|.+自治州)(?<county>[^县]+县|.+区|.+镇|.+局)?(?<town>[^区]+区|.+镇)?(?<village>.*)";
        Matcher m = Pattern.compile(regex).matcher(address);
        String province = null, city = null, county = null, town = null, village = null;
        List<Map<String, String>> table = new ArrayList<Map<String, String>>();
        Map<String, String> row = null;
        while (m.find()) {
            row = new LinkedHashMap<String, String>();
            province = m.group("province");
            row.put("province", province == null ? "" : province.trim());
            city = m.group("city");
            row.put("city", city == null ? "" : city.trim());
            county = m.group("county");
            row.put("county", county == null ? "" : county.trim());
            town = m.group("town");
            row.put("town", town == null ? "" : town.trim());
            village = m.group("village");
            row.put("village", village == null ? "" : village.trim());
            table.add(row);
        }
        return table;
    }

}
